﻿using ARSoft.Tools.Net.Dns;
using DomainNameServer.Models;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Windows.Forms;

namespace DSVISUAL
{
    public class DomainManager
    {
        private static DomainManager _inst;
        private static object lockObj = new object();
        public static DomainManager Instance
        {
            get
            {
                if (_inst == null)
                {
                    lock (lockObj)
                    {
                        return _inst ?? (_inst = new DomainManager());
                    }
                }
                return _inst;
            }
        }

        private DomainManager() { }
        private BindingSource bindingSource = new BindingSource();

        public DomainInfo AddDomain(string domain)
        {
            lock (lockObj)
            {
                if (!Regex.IsMatch(domain, @"\w+\.[a-zA-Z]+"))
                    throw new ArgumentException("invalid domain name");
                if (this.GetDomains().Any(x => x.Domain == domain.ToLower()))
                {
                    throw new ArgumentException("the domain using the name is already exists");
                }
                var d = new DomainInfo(domain.ToLower());
                d.Enabled = true;
                bindingSource.Add(d);
                return d;
            }
        }
        public DomainInfo Remove(string domain)
        {
            lock (lockObj)
            {
                DomainInfo d = null;
                var idx = this.GetDomains().FindIndex(x => x.Domain == domain.ToLower());
                if (idx != -1)
                {
                    d = this.GetDomains().ElementAt(idx);
                    bindingSource.RemoveAt(idx);
                }
                return d;
            }
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="dns"></param>
        /// <returns>is processed or not</returns>
        public void Resolute(QueryReceivedEventArgs dns)
        {
            lock (lockObj)
            {
                if (bindingSource.DataSource == null)
                    return;
                if (!(bindingSource.DataSource as List<DomainInfo>).Any(x => x.Enabled))
                {
                    return;
                }
                foreach (var item in (bindingSource.DataSource as List<DomainInfo>).Where(x => x.Enabled))
                {
                    item.Resolute(dns);
                }
            }
        }

        internal void DisableDomain(string v)
        {
            var item = (bindingSource.DataSource as List<DomainInfo>).Find(x => x.Domain == v);
            if (item != null)
            {
                item.Enabled = false;
            }
        }

        internal void EnableDomain(string v)
        {
            var item = (bindingSource.DataSource as List<DomainInfo>).Find(x => x.Domain == v);
            if (item != null)
            {
                item.Enabled = true;
            }
        }

        public List<DomainInfo> GetDomains()
        {
            lock (lockObj)
            {
                var items = (bindingSource.DataSource as List<DomainInfo>);
                foreach (var item in items)
                {
                    item.RecordList = item.RecordList.Where(x => x != null).ToList();
                }
                return items;
            }
        }

        public void SetDomains(BindingSource domains)
        {
            this.bindingSource = domains;
        }

        public DomainInfo LocalHost { get; set; }
        public object DataSource { get { return this.bindingSource; } }

        internal void RemoveAt(int item)
        {
            lock (lockObj)
            {
                this.bindingSource.RemoveAt(item);
            }
        }

        internal void RemoveAll()
        {
            lock (lockObj)
            {
                this.bindingSource.Clear();
            }
        }
    }
}
